home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / Storage / Bento / DocPriv.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  29.0 KB  |  1,018 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        DocPriv.cpp
  3.  
  4.     Contains:    Implementation for Private class for CMDocument.
  5.  
  6.     Owned by:    Vincent Lo
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>     3/15/96    DM        1295410: create list iterators on stack
  13.                                     (avoid mem thrash during purge)
  14.         <21>     8/21/95    VL        1278330, 1278315: Error code cleanup.
  15.         <20>     5/26/95    VL        1251403: Multithreading naming support.
  16.         <19>     5/25/95    jpa        List.h --> LinkList.h [1253324] Fixed
  17.                                     misuse of ODDebug [1253321]
  18.         <18>     4/14/95    EL        1239463: Remove Change should not reduce
  19.                                     version id to 0.
  20.         <17>     3/31/95    EL        1234685: ExportTo has extra parameter so we
  21.                                     can skip top draft. Dirty flag no longer
  22.                                     needed because version list only
  23.                                     externalized on close or flush.
  24.         <16>     3/29/95    DM        make standard format little endian
  25.         <15>     3/24/95    EL        1209355: dirty flag for version list. Temp
  26.                                     fix: remove duplicate drafts when version
  27.                                     list is read.
  28.         <14>     3/23/95    VL        1228003: Added Print.
  29.         <13>      3/9/95    VL        1226089: Introduced fHighestDraftID to
  30.                                     prevent DraftID from being reused in a
  31.                                     session.
  32.         <12>     2/15/95    EL        1182275: Add GetSameVersionDraftID to get
  33.                                     the lowest draft that has the same version
  34.                                     as the latest draft.
  35.         <11>     1/31/95    EL        1213321: Do not output tomstoned versions
  36.                                     during externalization.
  37.         <10>     1/11/95    VL        1185688: Made storage more robust in terms
  38.                                     of error handling. Also did some code
  39.                                     review cleanup.
  40.          <9>    11/14/94    VL        1188257: Use Bento errors in BenotDef.h.
  41.          <8>      9/5/94    VL        1184871: Remove dependency on default heap
  42.                                     by calling ODRecoverHeapID>
  43.          <7>     8/26/94    VL        1183174: Use updated GetSTorageUnitRef
  44.                                     which takes ID.
  45.          <6>     7/11/94    VL        Added Exists calls.
  46.          <5>      7/7/94    VL        Commented out use of ODRecoverHeapID.
  47.          <4>     6/28/94    VL        ODRecoverHeap to ODRecoverHeapID.
  48.          <3>     6/20/94    CC        ODMemoryHeap* changed to ODMemoryHeapID.
  49.          <2>     6/15/94    RR        ODHeap -> ODMemoryHeap
  50.          <1>     5/27/94    VL        first checked in
  51.  
  52.     To Do:
  53.         1) Get rid of tombstoned versions.
  54.     In Progress:
  55. */
  56.  
  57. #ifndef _DOCPRIV_
  58. #include "DocPriv.h"
  59. #endif
  60.  
  61. #ifndef _FLIPEND_
  62. #include "FlipEnd.h"
  63. #endif
  64.  
  65. #ifndef SOM_CMDocument_xh
  66. #include "CMDoc.xh"
  67. #endif
  68.  
  69. #ifndef _LINKLIST_
  70. #include "LinkList.h"
  71. #endif
  72.  
  73. #ifndef _EXCEPT_
  74. #include "Except.h"
  75. #endif
  76.  
  77. #ifndef _ODDEBUG_
  78. #include "ODDebug.h"
  79. #endif
  80.  
  81. #ifndef _ODMEMORY_
  82. #include "ODMemory.h"
  83. #endif
  84.  
  85. #ifndef _ODNEW_
  86. #include "ODNew.h"
  87. #endif
  88.  
  89. #ifndef SOM_CMDraft_xh
  90. #include "CMDraft.xh"
  91. #endif
  92.  
  93. #ifndef _BENTODEF_
  94. #include "BentoDef.h"
  95. #endif
  96.  
  97. #ifndef som_xh
  98. #include "som.xh"
  99. #endif
  100.  
  101. #pragma segment Document
  102.  
  103. //==============================================================================
  104. // Scalar Types
  105. //==============================================================================
  106.  
  107. #if ODDebug
  108. // #define DebugStorage 1
  109. #endif
  110.  
  111. #ifdef DebugStorage
  112. #define MyDebug3Str(f,p1,p2,p3) somPrintf(f, p1, p2, p3)
  113. #else
  114. #define MyDebug3Str(f,p1,p2,p3)
  115. #endif
  116.  
  117. typedef struct {
  118.     ODDraftID        draftID;
  119.     ODVersionID    versionID;
  120. } VersionRecord;
  121.  
  122. #ifdef STORAGE_TEST
  123. inline void BREAK_AND_THROW(ODError e)
  124. {
  125.     Debugger();
  126.     THROW(e);
  127. }
  128. #else
  129.  
  130. #define BREAK_AND_THROW(e)    THROW(e)
  131.  
  132. #endif
  133.  
  134.  
  135. //==============================================================================
  136. // DraftList
  137. //==============================================================================
  138.  
  139. //------------------------------------------------------------------------------
  140. // DraftList::DraftList
  141. //------------------------------------------------------------------------------
  142.  
  143. DraftList::DraftList()
  144. {
  145.     fHeap = kODNULL;
  146. }
  147.  
  148. //------------------------------------------------------------------------------
  149. // DraftList::~DraftList
  150. //------------------------------------------------------------------------------
  151.  
  152. DraftList::~DraftList()
  153. {
  154.     Link*    link;
  155.     
  156.     link = fLinkedList->RemoveFirst();
  157.     while (link != kODNULL) {
  158.         delete link;
  159.         link = fLinkedList->RemoveFirst();
  160.     }
  161.     delete fLinkedList;
  162. }
  163.  
  164. //------------------------------------------------------------------------------
  165. // DraftList::Initialize
  166. //------------------------------------------------------------------------------
  167.  
  168. void DraftList::Initialize()
  169. {
  170.     fHeap = ODRecoverHeapID(this);
  171.     
  172.     fLinkedList = new(GetHeap()) LinkedList;
  173. }
  174.  
  175.  
  176. //------------------------------------------------------------------------------
  177. // DraftList::Get
  178. //------------------------------------------------------------------------------
  179.  
  180. CMDraft* DraftList::Get(ODDraftID draftID)
  181. {    
  182.     DraftLink* link = this->GetLink(draftID);
  183.     
  184.     if (link == kODNULL)
  185.         return kODNULL;
  186.     return link->GetDraft();
  187. }
  188.  
  189. //------------------------------------------------------------------------------
  190. // DraftList::Add
  191. //------------------------------------------------------------------------------
  192.  
  193. void DraftList::Add(ODDraftID draftID, CMDraft* draft)
  194. {    
  195.     CMDraft* existingDraft;
  196.     DraftLink* link;
  197.     
  198.     if ((existingDraft = this->Get(draftID)) == kODNULL) {
  199.         link = new(GetHeap()) DraftLink(draftID, draft);
  200.         fLinkedList->AddLast(link);
  201.     }
  202.     else {
  203.         Environment* ev = somGetGlobalEnvironment();
  204.         if (draftID != existingDraft->GetID(ev))
  205.             BREAK_AND_THROW(kODErrDraftExistsWithDifferentID);
  206.     }
  207. }
  208.         
  209. //------------------------------------------------------------------------------
  210. // DraftList::Remove
  211. //------------------------------------------------------------------------------
  212.  
  213. void DraftList::Remove(ODDraftID draftID)
  214. {
  215.     DraftLink* link = this->GetLink(draftID);
  216.     
  217.     if (link == kODNULL)
  218.         BREAK_AND_THROW(kODErrDraftDoesNotExist);
  219.     else {
  220.         fLinkedList->Remove(*link);
  221.         delete link;
  222.     }
  223. }
  224.  
  225. //------------------------------------------------------------------------------
  226. // DraftList::Count
  227. //------------------------------------------------------------------------------
  228.  
  229. ODULong DraftList::Count()
  230. {
  231.     return fLinkedList->Count();
  232. }
  233.  
  234. //------------------------------------------------------------------------------
  235. // DraftList::GetLink
  236. //------------------------------------------------------------------------------
  237.  
  238. DraftLink* DraftList::GetLink(ODDraftID draftID)
  239. {
  240.     LinkedListIterator    iter(fLinkedList);
  241.     
  242.     DraftLink* link = (DraftLink*) iter.Last();
  243.     while ((link != kODNULL) && (link->GetDraftID() != draftID)) {
  244.         link = (DraftLink*) iter.Previous();
  245.     }
  246.     return link;
  247. }
  248.  
  249. //------------------------------------------------------------------------------
  250. // DraftList::GetHeap
  251. //------------------------------------------------------------------------------
  252.  
  253. ODMemoryHeapID DraftList::GetHeap()
  254. {
  255.     return fHeap;
  256. }
  257.  
  258. //------------------------------------------------------------------------------
  259. // DraftList::GetLinkedList
  260. //------------------------------------------------------------------------------
  261.  
  262. LinkedList* DraftList::GetLinkedList()
  263. {
  264.     return fLinkedList;
  265. }
  266.  
  267. //==============================================================================
  268. // DraftListIterator
  269. //==============================================================================
  270.  
  271. //------------------------------------------------------------------------------
  272. // DraftListIterator::DraftListIterator
  273. //------------------------------------------------------------------------------
  274.  
  275. DraftListIterator::DraftListIterator(DraftList* draftList)
  276.     : fDraftList(draftList), fIterator( draftList->GetLinkedList() )
  277. {
  278.     // fDraftList = draftList;
  279. }
  280.     
  281. //------------------------------------------------------------------------------
  282. // DraftListIterator::~DraftListIterator
  283. //------------------------------------------------------------------------------
  284.  
  285. DraftListIterator::~DraftListIterator()
  286. {
  287.     // delete fIterator;
  288. }
  289.  
  290. //------------------------------------------------------------------------------
  291. // DraftListIterator::Initialize
  292. //------------------------------------------------------------------------------
  293.  
  294. void DraftListIterator::Initialize()
  295. {
  296.     // fIterator = new(fDraftList->GetHeap()) LinkedListIterator(fDraftList->GetLinkedList());
  297. }
  298.     
  299.  
  300. //------------------------------------------------------------------------------
  301. // DraftListIterator::Last
  302. //------------------------------------------------------------------------------
  303.  
  304. CMDraft* DraftListIterator::Last()
  305. {
  306.     DraftLink* link = (DraftLink*) fIterator.Last();
  307.     if (link == kODNULL)
  308.         return kODNULL;
  309.     return link->GetDraft();
  310. }
  311.  
  312. //------------------------------------------------------------------------------
  313. // DraftListIterator::Previous
  314. //------------------------------------------------------------------------------
  315.  
  316. CMDraft* DraftListIterator::Previous()
  317. {
  318.     DraftLink* link = (DraftLink*) fIterator.Previous();
  319.     if (link == kODNULL)
  320.         return kODNULL;
  321.     return link->GetDraft();
  322. }
  323.         
  324. //------------------------------------------------------------------------------
  325. // DraftListIterator::IsNotComplete
  326. //------------------------------------------------------------------------------
  327.  
  328. ODBoolean DraftListIterator::IsNotComplete()
  329. {
  330.     return fIterator.IsNotComplete();
  331. }
  332.  
  333. //==============================================================================
  334. // VersionLink
  335. //==============================================================================
  336.  
  337. //------------------------------------------------------------------------------
  338. // VersionLink::VersionLink
  339. //------------------------------------------------------------------------------
  340.  
  341. VersionLink::VersionLink(ODDraftID draftID, ODVersionID versionID)
  342.     : Link()
  343. {
  344.     fDraftID = draftID;
  345.     fVersionID = versionID;
  346. }
  347.  
  348. //==============================================================================
  349. // VersionList
  350. //==============================================================================
  351.  
  352. //------------------------------------------------------------------------------
  353. // VersionList::VersionList
  354. //------------------------------------------------------------------------------
  355.  
  356. VersionList::VersionList()
  357. {
  358.     fHighestDraftID = 0;
  359.     fLatestVersionID = 0;
  360.     fLinkedList = kODNULL;
  361.     fHeap = kODNULL;
  362. }
  363.  
  364. //------------------------------------------------------------------------------
  365. // VersionList::~VersionList
  366. //------------------------------------------------------------------------------
  367.  
  368. VersionList::~VersionList()
  369. {
  370.     this->Clear();
  371.     delete fLinkedList;
  372. }
  373.  
  374. //------------------------------------------------------------------------------
  375. // VersionList::Initialize
  376. //------------------------------------------------------------------------------
  377.  
  378. void VersionList::Initialize()
  379. {
  380.     fHeap = ODRecoverHeapID(this);
  381.  
  382.     fLinkedList = new(GetHeap()) LinkedList;
  383. }
  384.  
  385. //------------------------------------------------------------------------------
  386. // VersionList::Initialize
  387. //------------------------------------------------------------------------------
  388.  
  389. void VersionList::Initialize(ODPtr buffer, ODULong size)
  390. {
  391.     VersionRecord*    versionList;
  392.     ODULong        numVersionRecords;
  393.     ODULong        i;
  394.     VersionLink*    link;
  395.  
  396.     // Note that I am assuming that VersionRecord contains just ODULong's
  397.     // without any additional padding:
  398.     ConvertODULongArrayFromStd((ODULong*) buffer, size / sizeof(ODULong));
  399.     
  400.     ASSERTM(size > 0, kODErrIllegalNullInput, "VersionList is empty.");
  401.     
  402.     fLatestVersionID = *((ODULong*) buffer);
  403.     
  404.     versionList = (VersionRecord*) (((ODSByte*) buffer) + sizeof(ODULong));
  405.     numVersionRecords = (size - sizeof(ODULong)) / sizeof(VersionRecord);
  406.     
  407.     fLinkedList = new(GetHeap()) LinkedList;
  408.     
  409.     ODVersionID        prevVersionID = kODTombstonedVersion;
  410.     
  411.     for (i = 0; i < numVersionRecords; i++) {
  412.         MyDebug3Str("Import %x: DraftID %d VersionID %d\n", this, versionList[i].draftID, versionList[i].versionID);
  413. #if TestFlushContainer
  414.         if (versionList[i].versionID != prevVersionID) {
  415. #endif
  416.         prevVersionID = versionList[i].versionID;
  417.         link = new(GetHeap()) VersionLink(versionList[i].draftID, prevVersionID);
  418.         fLinkedList->AddLast(link);
  419. #if TestFlushContainer
  420.         }
  421. #endif
  422.     }
  423. }
  424.  
  425. //------------------------------------------------------------------------------
  426. // VersionList::ExportTo
  427. //------------------------------------------------------------------------------
  428.  
  429. void VersionList::ExportTo(ODPtr* buffer, ODULong* size, ODBoolean ignoreTopDraft)
  430. {
  431.     LinkedListIterator    iter(fLinkedList);
  432.     ODULong            count = 0;
  433.     ODULong            i = 0;
  434.     VersionRecord*        versionList;
  435.     ODVersionID        thisVersionID;
  436.     
  437.     Link*    link = iter.First();
  438.     while (link != kODNULL) {
  439.         thisVersionID = ((VersionLink*) link)->GetVersionID();
  440.         // Ignore tombstone
  441.         if (thisVersionID != kODTombstonedVersion)
  442.             count++;
  443.         link = iter.Next();
  444.     }
  445.     
  446.     *size = sizeof(ODULong) + count * sizeof(VersionRecord);
  447.     *buffer = ODNewPtr(*size, GetHeap());
  448.  
  449.     if (ignoreTopDraft != kODFalse)
  450.         *size -= sizeof(VersionRecord);
  451.  
  452.     *((ODULong*) *buffer) = ConvertODULongToStd(fLatestVersionID);
  453.     
  454.     versionList = (VersionRecord*) (((ODSByte*) *buffer) + sizeof(ODULong));
  455.     
  456.     link = iter.First();
  457.     while (link != kODNULL) {
  458.         thisVersionID = ((VersionLink*) link)->GetVersionID();
  459.         // Ignore tombstone
  460.         if (thisVersionID != kODTombstonedVersion) {
  461.             versionList[i].draftID = ConvertODULongToStd(((VersionLink*) link)->GetDraftID());
  462.             versionList[i].versionID = ConvertODULongToStd(thisVersionID);
  463.             MyDebug3Str("Export %x: DraftID %d VersionID %d\n", this, versionList[i].draftID, versionList[i].versionID);
  464.             i++;
  465.         }
  466.         link = iter.Next();
  467.     }
  468. }
  469.  
  470. //------------------------------------------------------------------------------
  471. // VersionList::Reinitialize
  472. //------------------------------------------------------------------------------
  473.  
  474. void VersionList::Reinitialize(ODPtr buffer, ODULong size)
  475. {
  476.     this->Clear();
  477.     this->Initialize(buffer, size);
  478. }
  479.  
  480. //------------------------------------------------------------------------------
  481. // VersionList::CreateDraft
  482. //------------------------------------------------------------------------------
  483.  
  484. ODDraftID VersionList::CreateDraft()
  485. {
  486.     ODVersionID    versionID;
  487.     
  488.     VersionLink* prevLink = (VersionLink*) fLinkedList->Last();
  489.     if (prevLink == kODNULL) {
  490.         fHighestDraftID = 1;
  491.         versionID = 0;
  492.     }
  493.     else {
  494.         ODDraftID draftID = prevLink->GetDraftID();
  495.         if (draftID > fHighestDraftID)
  496.             fHighestDraftID = draftID;
  497.         fHighestDraftID++;
  498.         ODDraftID prevDraftID = this->GetLatestDraftID();
  499.         versionID = this->GetDraft(prevDraftID);
  500.     }
  501.     
  502.     VersionLink* link = new(GetHeap()) VersionLink(fHighestDraftID, versionID);
  503.     fLinkedList->AddLast(link);
  504.         
  505.     return fHighestDraftID;
  506. }
  507.  
  508. //------------------------------------------------------------------------------
  509. // VersionList::RemoveDraft
  510. //------------------------------------------------------------------------------
  511.  
  512. void VersionList::RemoveDraft(ODDraftID draftID)
  513. {
  514.     VersionLink* link = this->GetLink(draftID);
  515.     
  516.     if (link == kODNULL)
  517.         BREAK_AND_THROW(kODErrDraftDoesNotExist);
  518.     else {
  519.         fLinkedList->Remove(*link);
  520.         delete link;
  521.     }
  522. }
  523.  
  524. //------------------------------------------------------------------------------
  525. // VersionList::GetDraft
  526. //------------------------------------------------------------------------------
  527.  
  528. ODVersionID VersionList::GetDraft(ODDraftID draftID)
  529. {
  530.     VersionLink*    link = this->GetLink(draftID);
  531.     
  532.     if (link == kODNULL)
  533.         return kODTombstonedVersion;
  534.         
  535.     return link->GetVersionID();
  536. }
  537.  
  538. //------------------------------------------------------------------------------
  539. // VersionList::CreateVersion
  540. //------------------------------------------------------------------------------
  541.  
  542. ODVersionID VersionList::CreateVersion(ODDraftID draftID)
  543. {
  544.     VersionLink*    link;
  545.     ODDraftID        latestDraftID = this->GetLatestDraftID();
  546.     
  547.     if (latestDraftID != draftID)
  548.         BREAK_AND_THROW(kODErrIllegalNonTopmostDraft);
  549.     
  550.     link = this->GetLink(draftID);
  551.     if (link == kODNULL)
  552.         BREAK_AND_THROW(kODErrDraftDoesNotExist);
  553.  
  554.     fLatestVersionID++;
  555.     
  556.     link->SetVersionID(fLatestVersionID);
  557.     
  558.     return fLatestVersionID;
  559. }
  560.  
  561. //------------------------------------------------------------------------------
  562. // VersionList::GetCurrentVersion
  563. //------------------------------------------------------------------------------
  564.  
  565. ODVersionID VersionList::GetCurrentVersion(ODDraftID draftID)
  566. {
  567.     VersionLink*    link = this->GetLink(draftID);
  568.     
  569.     if (link == kODNULL)
  570.         BREAK_AND_THROW(kODErrDraftDoesNotExist);
  571.             
  572.     return link->GetVersionID();
  573. }
  574.  
  575. //------------------------------------------------------------------------------
  576. // VersionList::Exists
  577. //------------------------------------------------------------------------------
  578.  
  579. ODBoolean VersionList::Exists(ODDraftID draftID)
  580. {
  581.     VersionLink*    link = this->GetLink(draftID);
  582.     
  583.     if ((link == kODNULL) || (link->GetVersionID() == kODTombstonedVersion))
  584.         return kODFalse;
  585.     else
  586.         return kODTrue;
  587. }
  588.  
  589.  
  590. //------------------------------------------------------------------------------
  591. // VersionList::CollapseDrafts
  592. //------------------------------------------------------------------------------
  593.  
  594. void VersionList::CollapseDrafts(ODDraftID fromID, ODDraftID toID)
  595. {
  596.     ODVersionID    fromVersionID;
  597.     VersionLink*    versionLink;
  598.     ODVersionID    prevVersionID;
  599.  
  600.     // Check the Draft Topology
  601.     
  602.     VersionListIterator iter(this);
  603.     iter.Initialize();
  604.     
  605.     versionLink = iter.Last();
  606.     while ((versionLink != kODNULL) && (versionLink->GetDraftID() != fromID)) {
  607.         versionLink = iter.Previous();
  608.     }
  609.     fromVersionID = this->GetDraft(fromID);
  610.     versionLink = iter.Previous();
  611.     while ((versionLink != kODNULL) && (versionLink->GetDraftID() >= toID)) {
  612.         prevVersionID = versionLink->GetVersionID();
  613.         if ((prevVersionID != kODTombstonedVersion) && (fromVersionID != prevVersionID))
  614.             BREAK_AND_THROW(kODErrNonEmptyDraft);
  615.         versionLink = iter.Previous();
  616.     }
  617.  
  618.     // Do the actual updating
  619.     
  620.     versionLink = iter.Last();
  621.     while ((versionLink != kODNULL) && (versionLink->GetDraftID() != fromID)) {
  622.         versionLink = iter.Previous();
  623.     }    
  624.     while ((versionLink != kODNULL) && (versionLink->GetDraftID() > toID)) {
  625.         versionLink->SetVersionID(kODTombstonedVersion);
  626.         versionLink = iter.Previous();
  627.     }
  628.     // delete iter;
  629. }
  630.  
  631. //------------------------------------------------------------------------------
  632. // VersionList::SaveToAPrevDraft
  633. //------------------------------------------------------------------------------
  634.  
  635. void VersionList::SaveToAPrevDraft(ODDraftID fromID, ODDraftID toID)
  636. {
  637.     ODVersionID    fromVersionID;
  638.     VersionLink*    versionLink;
  639.     
  640.     fromVersionID = this->GetDraft(fromID);
  641.     
  642.     // Find the from draft
  643.     
  644.     VersionListIterator iter(this);
  645.     iter.Initialize();
  646.     versionLink = iter.Last();
  647.     while ((versionLink != kODNULL) && (versionLink->GetDraftID() != fromID)) {
  648.         versionLink = iter.Previous();
  649.     }
  650.     
  651.     // Do the actual update of the Version List
  652.     
  653.     versionLink = iter.Previous();
  654.     while ((versionLink != kODNULL) && (versionLink->GetDraftID() >= toID)) {
  655.         if (versionLink->GetVersionID() != kODTombstonedVersion)
  656.             versionLink->SetVersionID(fromVersionID);
  657.         versionLink = iter.Previous();
  658.     }
  659.     
  660.     // delete iter;
  661. }
  662.  
  663. //------------------------------------------------------------------------------
  664. // VersionList::RemoveChanges
  665. //------------------------------------------------------------------------------
  666.  
  667. ODVersionID VersionList::RemoveChanges(ODDraftID draftID)
  668. {
  669.     ODDraftID        prevDraftID;
  670.     VersionLink*    link;
  671.     ODVersionID    prevVersionID;
  672.         
  673.     link = this->GetLink(draftID);
  674.     if (link == kODNULL)
  675.         BREAK_AND_THROW(kODErrDraftDoesNotExist);
  676.  
  677.     if (draftID > 1) {
  678.         prevDraftID = this->GetPreviousDraftID(draftID);
  679.         prevVersionID = this->GetDraft(prevDraftID);
  680.     }
  681.     else {
  682. #if TestFlushContainer
  683.         prevVersionID = link->GetVersionID() - 1;
  684.         if (prevVersionID == 0)
  685.             prevVersionID = 1;
  686.         else
  687.             fLatestVersionID--;
  688. #else
  689.         prevVersionID = 0;
  690. #endif
  691.     }
  692.     
  693.     link->SetVersionID(prevVersionID);
  694.         
  695.     return prevVersionID;
  696. }
  697.  
  698. //------------------------------------------------------------------------------
  699. // VersionList::ChangedFromPrev
  700. //------------------------------------------------------------------------------
  701.  
  702. ODBoolean VersionList::ChangedFromPrev(ODDraftID draftID)
  703. {
  704.     ODDraftID        prevDraftID;
  705.     ODVersionID    versionID;
  706.     ODVersionID    prevVersionID;
  707.     ODDraftID        baseDraftID = this->GetBaseDraftID();
  708.  
  709.     if (draftID == baseDraftID) 
  710.         return kODFalse;
  711.  
  712.     versionID = this->GetDraft(draftID);
  713.  
  714.     prevDraftID = this->GetPreviousDraftID(draftID);
  715.     prevVersionID = this->GetDraft(prevDraftID);
  716.  
  717.     if (versionID == prevVersionID)
  718.         return kODFalse;
  719.     else
  720.         return kODTrue;
  721. }
  722.  
  723. //------------------------------------------------------------------------------
  724. // VersionList::GetBaseDraftID
  725. //------------------------------------------------------------------------------
  726.  
  727. ODDraftID VersionList::GetBaseDraftID()
  728. {
  729.     VersionLink* link = (VersionLink*) fLinkedList->First();
  730.     
  731.     if (link == kODNULL)
  732.         return (ODDraftID) 1;
  733.     else
  734.         return link->GetDraftID();
  735. }
  736.  
  737. //------------------------------------------------------------------------------
  738. // VersionList::GetLatestDraftID
  739. //------------------------------------------------------------------------------
  740.  
  741. ODDraftID VersionList::GetLatestDraftID()
  742. {
  743.     VersionLink*     versionLink;
  744.  
  745.     versionLink = (VersionLink*) fLinkedList->Last();
  746.     
  747.     while ((versionLink != kODNULL) && 
  748.             (versionLink->GetVersionID() == kODTombstonedVersion)) {
  749.         versionLink = (VersionLink*) fLinkedList->Before(*versionLink);
  750.     }
  751.     
  752.     if (versionLink == kODNULL)
  753.         return this->GetBaseDraftID();
  754.     else
  755.         return versionLink->GetDraftID();
  756. }
  757.  
  758. //------------------------------------------------------------------------------
  759. // VersionList::GetPreviousDraftID
  760. //------------------------------------------------------------------------------
  761.  
  762. ODDraftID VersionList::GetPreviousDraftID(ODDraftID curDraftID)
  763. {
  764.     VersionLink*    curVersionLink;
  765.     ODDraftID        baseDraftID = this->GetBaseDraftID();
  766.     VersionLink*    versionLink;
  767.     
  768.     if (baseDraftID == curDraftID)
  769.         BREAK_AND_THROW(kODErrNoPreviousDraft);
  770.     if ((curVersionLink = this->GetLink(curDraftID)) != kODNULL) {
  771.         versionLink = (VersionLink*) fLinkedList->Before(*curVersionLink);
  772.         while (versionLink != kODNULL) {
  773.             if (versionLink->GetVersionID() != kODTombstonedVersion)
  774.                 return versionLink->GetDraftID();
  775.             versionLink = (VersionLink*) fLinkedList->Before(*versionLink);
  776.         }
  777.     }
  778.     BREAK_AND_THROW(kODErrDraftDoesNotExist);
  779.     
  780.     return 0;            // To avoid unnecessary warning from the compiler.
  781. }
  782.  
  783. //------------------------------------------------------------------------------
  784. // VersionList::GetSameVersionDraftID
  785. //------------------------------------------------------------------------------
  786.  
  787. ODDraftID VersionList::GetSameVersionDraftID(ODDraftID curDraftID)
  788. {
  789.     ODDraftID        baseDraftID = this->GetBaseDraftID(), sameVersionDraftID, draftID;
  790.     ODVersionID     latestVersion;
  791.  
  792.     sameVersionDraftID = curDraftID;
  793.     latestVersion = this->GetCurrentVersion(sameVersionDraftID);
  794.     
  795.     if (sameVersionDraftID != baseDraftID) {
  796.         draftID = this->GetPreviousDraftID(sameVersionDraftID);
  797.         while (draftID >= baseDraftID) {
  798.             if (latestVersion == this->GetCurrentVersion(draftID)) {
  799.                 sameVersionDraftID = draftID;
  800.                 if (draftID != baseDraftID)
  801.                     draftID = this->GetPreviousDraftID(draftID);
  802.                 else
  803.                     draftID = 0;
  804.             }
  805.             else
  806.                 draftID = 0;
  807.         };
  808.     }
  809.     return sameVersionDraftID;
  810. }
  811.  
  812. //------------------------------------------------------------------------------
  813. // VersionList::PreviousDraftExists
  814. //------------------------------------------------------------------------------
  815.  
  816. ODBoolean VersionList::PreviousDraftExists(ODDraftID curDraftID)
  817. {
  818.     VersionLink*    curVersionLink;
  819.     ODDraftID        baseDraftID = this->GetBaseDraftID();
  820.     VersionLink*    versionLink;
  821.     
  822.     if (baseDraftID == curDraftID)
  823.         return kODFalse;
  824.     if ((curVersionLink = this->GetLink(curDraftID)) != kODNULL) {
  825.         versionLink = (VersionLink*) fLinkedList->Before(*curVersionLink);
  826.         while (versionLink != kODNULL) {
  827.             if (versionLink->GetVersionID() != kODTombstonedVersion)
  828.                 return kODTrue;
  829.             versionLink = (VersionLink*) fLinkedList->Before(*versionLink);
  830.         }
  831.     }    
  832.     return kODFalse;
  833. }
  834.  
  835. //------------------------------------------------------------------------------
  836. // VersionList::GetNextDraftID
  837. //------------------------------------------------------------------------------
  838.  
  839. ODDraftID VersionList::GetNextDraftID(ODDraftID curDraftID)
  840. {
  841.     VersionLink*    curVersionLink;
  842.     VersionLink*    versionLink;
  843.     
  844.     if ((curVersionLink = this->GetLink(curDraftID)) != kODNULL) {
  845.         versionLink = (VersionLink*) fLinkedList->After(*curVersionLink);
  846.         while (versionLink != kODNULL) {
  847.             if (versionLink->GetVersionID() != kODTombstonedVersion)
  848.                 return versionLink->GetDraftID();
  849.             versionLink = (VersionLink*) fLinkedList->After(*versionLink);
  850.         }
  851.     }
  852.     BREAK_AND_THROW(kODErrDraftDoesNotExist);
  853.     
  854.     return 0;            // To avoid unnecessary warning from the compiler.
  855. }
  856.  
  857. //------------------------------------------------------------------------------
  858. // VersionList::NextDraftExists
  859. //------------------------------------------------------------------------------
  860.  
  861. ODBoolean VersionList::NextDraftExists(ODDraftID curDraftID)
  862. {
  863.     VersionLink*    curVersionLink;
  864.     VersionLink*    versionLink;
  865.     
  866.     if ((curVersionLink = this->GetLink(curDraftID)) != kODNULL) {
  867.         versionLink = (VersionLink*) fLinkedList->After(*curVersionLink);
  868.         while (versionLink != kODNULL) {
  869.             if (versionLink->GetVersionID() != kODTombstonedVersion)
  870.                 return kODTrue;
  871.             versionLink = (VersionLink*) fLinkedList->After(*versionLink);
  872.         }
  873.     }    
  874.     return kODFalse;
  875. }
  876.  
  877. //------------------------------------------------------------------------------
  878. // VersionList::IsAbove
  879. //------------------------------------------------------------------------------
  880.  
  881. ODBoolean VersionList::IsAbove(ODDraftID draftID1, ODDraftID draftID2)
  882. {
  883.     return (draftID1 > draftID2);
  884. }
  885.  
  886. //------------------------------------------------------------------------------
  887. // VersionList::IsBelow
  888. //------------------------------------------------------------------------------
  889.  
  890. ODBoolean VersionList::IsBelow(ODDraftID draftID1, ODDraftID draftID2)
  891. {
  892.     return (draftID1 < draftID2);
  893. }
  894.  
  895. //------------------------------------------------------------------------------
  896. // VersionList::GetLink
  897. //------------------------------------------------------------------------------
  898.  
  899. VersionLink* VersionList::GetLink(ODDraftID draftID)
  900. {
  901.     LinkedListIterator    iter(fLinkedList);
  902.     
  903.     VersionLink* link = (VersionLink*) iter.Last();
  904.     while ((link != kODNULL) && (link->GetDraftID() != draftID)) {
  905.         link = (VersionLink*) iter.Previous();
  906.     }
  907.     return link;
  908. }
  909.  
  910. //------------------------------------------------------------------------------
  911. // VersionList::Clear
  912. //------------------------------------------------------------------------------
  913.  
  914. void VersionList::Clear()
  915. {
  916.     Link*    link;
  917.     
  918.     link = fLinkedList->RemoveFirst();
  919.     while (link != kODNULL) {
  920.         delete link;
  921.         link = fLinkedList->RemoveFirst();
  922.     }
  923. }
  924.  
  925. //------------------------------------------------------------------------------
  926. // VersionList::GetHeap
  927. //------------------------------------------------------------------------------
  928.  
  929. ODMemoryHeapID VersionList::GetHeap()
  930. {
  931.     return fHeap;
  932. }
  933.  
  934. //------------------------------------------------------------------------------
  935. // VersionList::GetLinkedList
  936. //------------------------------------------------------------------------------
  937.  
  938. LinkedList* VersionList::GetLinkedList()
  939. {
  940.     return fLinkedList;
  941. }
  942.  
  943. //------------------------------------------------------------------------------
  944. // VersionList::Print
  945. //------------------------------------------------------------------------------
  946.  
  947. void VersionList::Print(char* string)
  948. {
  949. #if ODDebug
  950.     VersionListIterator*    versionList = new VersionListIterator(this);
  951.     versionList->Initialize();
  952.     for (VersionLink* link = versionList->Last(); versionList->IsNotComplete(); link = versionList->Previous()) {
  953.         somPrintf("%s: draftID %d versionID %d\n", string, link->GetDraftID(), link->GetVersionID());
  954.     }
  955.     delete versionList;
  956. #endif
  957. }
  958.  
  959. //==============================================================================
  960. // VersionListIterator
  961. //==============================================================================
  962.  
  963. //------------------------------------------------------------------------------
  964. // VersionListIterator::VersionListIterator
  965. //------------------------------------------------------------------------------
  966.  
  967. VersionListIterator::VersionListIterator(VersionList* versionList)
  968.     : fVersionList(versionList), fIterator( versionList->GetLinkedList() )
  969. {
  970.     // fVersionList = versionList;
  971.     // fIterator = kODNULL;
  972. }
  973.     
  974. //------------------------------------------------------------------------------
  975. // VersionListIterator::~VersionListIterator
  976. //------------------------------------------------------------------------------
  977.  
  978. VersionListIterator::~VersionListIterator()
  979. {
  980.     // delete fIterator;
  981. }
  982.  
  983. //------------------------------------------------------------------------------
  984. // VersionListIterator::Initialize
  985. //------------------------------------------------------------------------------
  986.  
  987. void VersionListIterator::Initialize()
  988. {
  989.     // fIterator = new(fVersionList->GetHeap()) LinkedListIterator(fVersionList->GetLinkedList());
  990. }
  991.  
  992. //------------------------------------------------------------------------------
  993. // VersionListIterator::Last
  994. //------------------------------------------------------------------------------
  995.  
  996. VersionLink* VersionListIterator::Last()
  997. {
  998.     return (VersionLink*) fIterator.Last();
  999. }
  1000.  
  1001. //------------------------------------------------------------------------------
  1002. // VersionListIterator::Previous
  1003. //------------------------------------------------------------------------------
  1004.  
  1005. VersionLink* VersionListIterator::Previous()
  1006. {
  1007.     return (VersionLink*) fIterator.Previous();
  1008. }
  1009.         
  1010. //------------------------------------------------------------------------------
  1011. // VersionListIterator::IsNotComplete
  1012. //------------------------------------------------------------------------------
  1013.  
  1014. ODBoolean VersionListIterator::IsNotComplete()
  1015. {
  1016.     return fIterator.IsNotComplete();
  1017. }
  1018.